<?php

class TenpayAction extends Action{
	
	public function notifypay() {
        $sn = $_GET['sp_billno'];

        $OrderModel = M("module_product_order");
        $whereOrderSn["serialNumber"] = $sn;
        $customerId = $OrderModel->where($whereOrderSn)->getField('fromCustomerId');
        if (!$customerId) {
            Log::write("[tenpay - notifypay failed sn:]" . $sn);
            echo "fail";
            return;
        }
        
        Log::write('in notify tenpay:' . $OrderModel->getLastSql());
        $setting = $this->getMallTenpaySettingByCid($customerId);
        if (!$setting) {
            echo "fail";
            return;
        }
        
        
        /* 商户号 */
        $partner = $setting["mchId"];
        
        /* 密钥 */
        $key = $setting["payKey"];
        
        /* 创建支付应答对象 */
        $resHandler = new WapNotifyResponseHandler();
        $resHandler->setKey($key);
        
        //判断签名
        if($resHandler->isTenpaySign()) {
            //财付通交易单号
            $transactionId = $resHandler->getParameter("transaction_id");
            //支付结果
            $pay_result = $resHandler->getParameter("pay_result");
            
            if( "0" == $pay_result  ) {
                $oidArr = $OrderModel->where($whereOrderSn)->getField('id' ,true);
                $oid = implode(",", $oidArr);
                $result = ProductOrder::updateOrderDone(0, $oid, $transactionId, true);
                if ($result) {
                    echo "success";
                } else {
                    echo "fail";
                }
            }
            else {
                echo "fail";
            } 
            
        } else {
            //回调签名错误
            echo "fail";
        }
	}
	
	
	/*
	 * 获取支付参数
	 * sn:订单编号，如果需要自动生成订单编号该值传0
	 * desc:商品描述显示在微信支付界面中
	 * productFee:产品价格
	 * transportFee:运费单位分
	 * userName:用户openid
	 * module:回调模块，如果产品传NULL，按照正常逻辑处理
	 * moduleId:回调模块id
	 * method:回调方法
	 */
	
    public function submitTenpay($sn, $price, $desc, $retUrl) {
        $setting = $this->getMallTenpaySetting();
        if (!$setting) {
            return;
        }
        
        /* 商户号 */
        $partner = $setting["mchId"];
        /* 密钥 */
        $key = $setting["payKey"];
        
        
		$ip = get_client_ip();
		$notifyUrl = C('SERVER_HOST') . "Tenpay/notifypay.json";
		
        
        //4位随机数
        $randNum = rand(1000, 9999);
        
        /* 创建支付请求对象 */
        $reqHandler = new RequestHandler();
        $reqHandler->init();
        $reqHandler->setKey($key);
        //$reqHandler->setGateUrl("https://gw.tenpay.com/gateway/pay.htm");
        //设置初始化请求接口，以获得token_id
        $reqHandler->setGateUrl("http://wap.tenpay.com/cgi-bin/wappayv2.0/wappay_init.cgi");
        
        
        $httpClient = new TenpayHttpClient();
        //应答对象
        $resHandler = new ClientResponseHandler();
        //----------------------------------------
        //设置支付参数
        //----------------------------------------
        $reqHandler->setParameter("total_fee", strval($price * 100));  //总金额
        //用户ip
        $reqHandler->setParameter("spbill_create_ip", $ip);//客户端IP
        $reqHandler->setParameter("ver", "2.0");//版本类型
        $reqHandler->setParameter("bank_type", "0"); //银行类型，财付通填写0
        $reqHandler->setParameter("callback_url", $retUrl);//交易完成后跳转的URL
        $reqHandler->setParameter("bargainor_id", $partner); //商户号
        $reqHandler->setParameter("sp_billno",strval($sn)); //商户订单号
        $reqHandler->setParameter("notify_url",  $notifyUrl);//接收财付通通知的URL，需绝对路径
        $reqHandler->setParameter("desc", $desc);
        //		$reqHandler->setParameter("attach", "1_xs_酷币");
        
        
        $httpClient->setReqContent($reqHandler->getRequestURL());
        
        //后台调用
        if($httpClient->call()) {
            
            $resHandler->setContent($httpClient->getResContent());
            //获得的token_id，用于支付请求
            $token_id = $resHandler->getParameter('token_id');
            
            $reqHandler->setParameter("token_id", $token_id);
            
            //请求的URL
            //$reqHandler->setGateUrl("https://wap.tenpay.com/cgi-bin/wappayv2.0/wappay_gate.cgi");
            //此次请求只需带上参数token_id就可以了，$reqUrl和$reqUrl2效果是一样的
            //$reqUrl = $reqHandler->getRequestURL(); 
            $reqUrl = "http://wap.tenpay.com/cgi-bin/wappayv2.0/wappay_gate.cgi?token_id=".$token_id;
            $result["url"] = $reqUrl;
            Output::instance()->object($result);
        } else {
			Output::instance()->resultCode(code_system_error);
		}
	}

    
    public function tenpayRefund($oid, $sn, $refundId, $org_amount, $refund_amount, $refundPwd){
        $setting = $this->getMallTenpaySetting();
        if (!$setting) {
            return;
        }
        
        /* 商户号 */
        $partner = $setting["mchId"];
        /* 密钥 */
        $key = $setting["payKey"];
        $password = $setting["password"];
        
        $filePem = WXPAY_CERT_PATH . ORDER_PAYTYPE_TENPAY  . $partner . ".pem";
        $filePemCert = WXPAY_CERT_PATH . ORDER_PAYTYPE_TENPAY . "cert.pem";

        
        if (!file_exists($filePem) || !file_exists($filePemCert)) {
            Log::write('refund pem not exisit ' . $filePem . ',' . $filePemCert);
            Output::instance()->resultCode(code_product_order_refund_pem_not_exist);
            return;
        }

        
        
        $reqHandler = new RequestHandler();
        
        //通信对象
        $httpClient = new TenpayHttpClient();
        
        //应答对象
        $resHandler = new ClientResponseHandler();
        
        //-----------------------------
        //设置请求参数
        //-----------------------------
        $reqHandler->init();
        $reqHandler->setKey($key);
        
        $reqHandler->setGateUrl("https://mch.tenpay.com/refundapi/gateway/refund.xml");
        $reqHandler->setParameter("partner", $partner);
        
        //out_trade_no和transaction_id至少一个必填，同时存在时transaction_id优先
        $reqHandler->setParameter("out_trade_no", $sn);
        //必须保证全局唯一，同个退款单号财付通认为是同笔请求
        $reqHandler->setParameter("out_refund_no", $refundId);
        $reqHandler->setParameter("total_fee", $org_amount);
        $reqHandler->setParameter("refund_fee", $refund_amount);
        $reqHandler->setParameter("op_user_id", $partner);
        //操作员密码,MD5处理
        $reqHandler->setParameter("op_user_passwd", md5($refundPwd));
        //接口版本号,取值1.1
        $reqHandler->setParameter("service_version", "1.1");
        $reqHandler->setParameter("input_charset", "UTF-8");
        
        
        //-----------------------------
        //设置通信参数
        //-----------------------------
        //设置PEM证书
        $httpClient->setCertInfo($filePem, $password);
        //设置CA
        $httpClient->setCaInfo($filePemCert);
        $httpClient->setTimeOut(5);
        $httpClient->setMethod("post");
        //设置请求内容
        $httpClient->setReqContent($reqHandler->getRequestURL());
        
    
        //后台调用
        if($httpClient->call()) {
            //设置结果参数
            $resHandler->setContent($httpClient->getResContent());
            $resHandler->setKey($key);
            
            //判断签名及结果
            //只有签名正确并且retcode为0才是请求成功
            if($resHandler->isTenpaySign() && $resHandler->getParameter("retcode") == 0 ) {
                R('Product/refundStatistics', array($oid,$refund_amount));

                ProductOrder::updateOrderRefund($oid, $refundId, true, '');
                Output::instance()->resultCode();
            } else {
                //错误时，返回结果可能没有签名，记录retcode、retmsg看失败详情。
                ProductOrder::updateOrderRefund($oid, $refundId, false, $resHandler->getParameter("retmsg"));
                
                Log::write("验证签名失败 或 业务错误信息:retcode=" . $resHandler->getParameter("retcode"). ",retmsg=" . $resHandler->getParameter("retmsg"));
                
                Output::instance()->resultCode(code_product_order_refund_failed, $resHandler->getParameter("retmsg"));
            }
            
        } else {
            //有可能因为网络原因，请求已经处理，但未收到应答。
            Output::instance()->resultCode(code_product_order_refund_failed, $httpClient->getErrInfo());
            
            Log::write("call err:" . $httpClient->getResponseCode() ."," . $httpClient->getErrInfo());
        }
         
        
    }
    
    private function getMallTenpaySettingByCid($customerId) {
        Session::switchCustomer(0);
        $MallSetting = M("customer_mall_tenpay_setting");
        $where["customerId"] = $customerId;
        $setting = $MallSetting->where($where)->find();
        Session::switchCustomer($customerId);
        if (!$setting) {
            Log::write($MallSetting->getLastSql());
            Output::instance()->resultCode(code_mall_setting_not_found);
            return;
        }
        
        if (empty($setting["mchId"]) || empty($setting["payKey"])) {
            Output::instance()->resultCode(code_mall_setting_invalid);
            return;
        }
        
        return $setting;
    }
    
    private function getMallTenpaySetting() {
        $retVal = Session::init();
        if (!$retVal) {
            Output::instance()->resultCode(code_access_denied);
            return;
        }
        
        $customerId = Session::$user["customerId"];
        $setting = $this->getMallTenpaySettingByCid($customerId);
        return $setting;
    }
	
}